package com.chat.core.service.impl;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chat.core.dao.ChatSessionDao;
import com.chat.core.dao.ChatSessionReadDao;
import com.chat.core.dao.UserDao;
import com.chat.core.entity.ChatSession;
import com.chat.core.entity.ChatSessionRead;
import com.chat.core.entity.User;
import com.chat.core.service.UserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户(User)表服务实现类
 *
 * @author makejava
 * @since 2022-04-11 13:43:48
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Value("${md5.salt}")
    private String salt;

    @Resource
    private ChatSessionDao chatSessionDao;
    @Resource
    private ChatSessionReadDao chatSessionReadDao;


    @Override
    public User login(String username, String password) throws IOException {
        Digester digester = SecureUtil.md5().setSalt(salt.getBytes());
        String pwd = digester.digestHex(password.trim());
        String name = digester.digestHex(username.trim());
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name",name);
        User one = this.getOne(wrapper);
        Assert.notNull(one,"用户名错误！");
        Assert.isTrue(one.getPassword().equals(pwd),"用户密码错误！");
        Map<String, Object> map = new HashMap<>();
        map.put("msg","用户："+ one.getUserNick()+",已上线！");
        map.put("code",101);
        map.put("count",WsSessionManager.getNum());
        WsSessionManager.sendGroupMessage(one.getId(), JSONUtil.toJsonPrettyStr(map));
        return one;
    }

    @Override
    public boolean register(User user) {
        Digester digester = SecureUtil.md5().setSalt(salt.getBytes());
        String name = digester.digestHex(user.getUserName().trim());
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name",name);
        User one = this.getOne(wrapper);
        Assert.isNull(one,"用户名已存在！");
        String pwd = digester.digestHex(user.getPassword().trim());
        if (user.getPortraitUrl()==null) user.setPortraitUrl("123.png");
        user.setPassword(pwd);
        user.setUserName(name);
        return this.save(user);
    }

    @Override
    public List<User> getOnlineList() {
        ArrayList<Integer> list = Collections.list(WsSessionManager.getKey());
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (list.size()>0) wrapper.in("id",list);
        return  this.list(wrapper);
    }

    @Override
    public List<User> getChatUserList(Integer id) {
        QueryWrapper<ChatSession> wrapper = new QueryWrapper<>();
        wrapper.eq("REVISION",1);
        wrapper.and(w ->  w.eq("CRT_USER_ID",id).or().eq("USER_ID",id));
        List<ChatSession> chatSessions = chatSessionDao.selectList(wrapper);
        List<Integer> ids = chatSessions.stream().map(x -> x.getCrtUserId().equals(id) ? x.getUserId() : x.getCrtUserId()).collect(Collectors.toList());
        if (ids.size()==0)return null;
        List<User> users = this.getBaseMapper().selectBatchIds(ids);
        return users.stream().peek(x->{
            Enumeration<Integer> key = WsSessionManager.getKey();
            while (key.hasMoreElements()){
                Integer userId = key.nextElement();
                if (x.getId().equals(userId)){
                    x.setOnline(true);
                }
            }
            chatSessions.forEach(w->{
                QueryWrapper<ChatSessionRead> readQueryWrapper = new QueryWrapper<>();
                readQueryWrapper.eq("CHAT_SESSION_ID",w.getId());
                List<ChatSessionRead> chatSessionReads = chatSessionReadDao.selectList(readQueryWrapper);
                Long count = chatSessionReads.stream().filter(c->c.getReadState()==0&& !c.getCrtUserId().equals(id)).count();
                if (chatSessionReads.size()>0){
                    Date date =  chatSessionReads.stream().filter(c -> c.getCrtDate() != null)
                            .map(ChatSessionRead::getCrtDate).max(Date::compareTo).orElse(chatSessionReads.get(0).getCrtDate());
                    chatSessionReads.stream().filter(s->s.getCrtDate().equals(date)).map(ChatSessionRead::getContent).findFirst().ifPresent(x::setContent);
                    x.setCount(count);
                    x.setEndDate(date);
                }else {
                    x.setEndDate(w.getCrtDate());
                }
            });
        }).collect(Collectors.toList());

    }

    @Override
    public boolean updateUser(User user) {
        Digester digester = SecureUtil.md5().setSalt(salt.getBytes());
        String name = digester.digestHex(user.getUserName());
        User newUser = this.getById(user.getId());
        Assert.isTrue(!newUser.getUserName().equals(name),"用户名已存在！修改失败");
        return  this.updateById(user);
    }
}
